﻿using System;
using com.youzu.warh.protocol;
using LogSystem;
using UnityEngine;

namespace Yoozoo.Gameplay.Liberty.AI
{
    [Flags]
    public enum AIState
    {
        None = 0,
        WaitingLight = 1,       // 正在等待红绿灯
        PassingLight = 2,       // 正在通过红绿灯
    }
    
    /*
     * Tips:
     * 1. 新增NpcStatus后，请修改AIData的canBeThreaten方法告知该状态是否可以被恐吓；
     * 2. 新增NpcStatus后，请修改AIData的canBeBarge方法告知该状态是否可以被推开；
     */
    [Flags]
    public enum NpcStatus
    {
        None = 0,
        PathControl = 1 << 0,
        PlayerControl = 1 << 1,   // 在玩家检测半径中
        PlayerBarge = 1 << 2,     // 被玩家撞击
        PlayerObstacle = 1 << 3,  // 被玩家阻挡
        StaticAction = 1 << 4,   // 播放静态行为
        OnHit = 1 << 5,        // 受击行为 
        Escape = 1 << 6,        // 逃跑行为 
        VehicleBarge = 1 << 7, // 被车辆撞击
        Battle = 1 << 8,    // 战斗状态
        EnterCar = 1 << 16,  // 主角开始进入车辆
        InCar = 1 << 17,     // 主角或Npc在车辆里
        ExitCar = 1 << 18,   // 主角开始从车辆里出去
        ExpelCar = 1 << 19,  // Npc被赶出车辆
    }

    // NPC类型
    /*
     * Tips:
     * 1. 新增NPC类型后，请修改AIData的defaultNpcStatus方法告知该类型的AI默认状态；
     */
    [Flags]
    public enum NpcStyle
    {
        None = 0,
        PathWalker = 1,
        Static = 2,
        Fare = 4,        // 默认在车上的Npc
        StreetEvent = 8,
    }
    
    // NPC武器类型 (配置在GTA_weapon表中的ai_behaviour字段)
    public enum NpcAIBehaviour
    {
        None = 0,
        Boxing = 2, // 近战AI
        HandGun = 3, // 枪械AI
        Grenade = 4, // 手雷AI
        RPG = 5,    // 火箭筒AI
    }

    // NPC行为模型 （配置在rpg_npc表中的ai_model字段）
    public enum NpcAIModel
    {
        None = 0,
        Escape = 1, // 逃跑
        ImmovableAttack = 2, // 禁止移动
        StandStillAttack = 3, // 移动过后，原地攻击
        HorzontalSShapeMoveAttack = 4, // S型移动攻击（横向左右移动）
        VerticleSShapeMoveAttack = 5, // S型移动攻击（纵向前后移动）
        PlayerFollower = 6, // 跟随玩家
        RandomSShapeMoveAttack = 7, // S型移动攻击（随机移动）
    }
    
    // 当前人物所属阵营
    /*
     * Tips:
     * 1. 新增阵营后，请修改BattleAgent的CheckEnemyByTag方法告知阵营是否敌对；
     */
    public enum SideType
    {
        // 玩家
        Player = 0,
        // Npc (跟玩家敌对)
        Npc = 1,
        // 玩家队友
        Teammate = 2,
        // 受保护的对象
        Protected = 3,
        // 小游戏竞争对手 （不可被玩家锁定，也不会攻击玩家）
        GameOpponent = 4,
        // 所有其他对象都是敌人
        Madness = 5,
        
        // 手雷 (特殊，给武器使用)
        Grenade = 10000,
        // RPG (特殊，给武器使用)
        RPG = 10001,
    }
    
    // 目标类型
    public enum TargetType
    {
        // 仇恨目标
        RevengeTarget = 0,
        // 当前锁定目标
        CurrentLockTarget = 1,
        // 最近目标
        PossibleTarget = 2,
        // 自己
        Self = 3,
        // 玩家
        Player = 4,
        // 追击仇恨目标
        ChaseRevengeTarget = 5, 
    }

    // 比较方式
    public enum CompareType
    {
        // 等于
        Equal = 1,
        // 小于
        Less = 2,
        // 小于等于
        LessEqual = 3,
        // 大于
        Greater = 4,
        // 大于等于
        GreaterEqual = 5,
        // 不等于
        NotEqual = 6,
    }
    
    // 返回值类型
    public enum ReturnValueType
    {
        // 返回成功
        ReturnSuccess = 1,
        // 返回失败
        ReturnFailure = 2,
        // 返回执行结果
        ReturnResult = 3,
    }

    // 当前人物动画状态
    /* 
     * Tips:
     * 1. 新增动画状态后，请修改AIData的cannotAnimationStateMove方法告知该状态是否可移动；
     * 2. 新增动画状态后，检查该状态是否作用于upperLayer，如果是，请修改AIData的animationState方法告知当前角色动画状态；
     * 3. 新增动画状态后，请修改AIData的canBeThreaten方法告知该角色动画状态是否可以被恐吓；
     * 4. 新增动画状态后，请修改AnimationAgent的CanDoNextAnimation方法告知该角色动画状态是否可以接下个动作；
     * 5. 新增动画状态后，请修改AIData的hasRootMotion方法告知是否含有根位移；
     * 6. 
     */
    public enum AnimationState
    {
        Undefine = 0,
        Idle = 1,   // 待机
        Locomotion = 2, // 移动
        BoxingAttackDown = 3,   // 近战向下攻击
        BoxingAttackKick = 4,   // 近战踢腿
        BoxingCombo1 = 5,   // 近战连招1
        BoxingCombo2 = 6,   // 近战连招2
        BoxingCombo3 = 7,   // 近战连招3
        HandGunShoot = 8,   // 手枪射击
        HandGunReload = 9,  // 手枪装弹
        OnHit = 10, // 受击
        OnHitDown = 11, // 受击倒地
        OnHitGetUp = 12, // 受击倒地
        BehaviourPuppet = 13,   // 布娃娃
        HandGunBoxing = 15, // 手枪近战
        BoxingMove = 16,    // 近战位移
        BoxingRunAttack = 17,   // 近战跑动攻击
        BoxingAOE = 18,   // 近战AOE
        BoxingAOE_1 = 19,   // 近战AOE-1段伤害 (仅用于伤害触发)
        BoxingAOE_2 = 20,   // 近战AOE-2段伤害 (仅用于伤害触发)
        Sprinting = 21,     // 玩家冲刺
        Dodge = 22,     // 玩家闪避
        HandGunAim = 23, // 手枪瞄准
        BoxingAim = 24,	// 近战瞄准
        AutoRifleAim = 25,	// 自动步枪瞄准
        AutoRifleShoot = 26,	// 自动步枪射击
        AutoRifleReload = 27,	// 自动步枪装弹
        BombAim = 29,	// 手雷瞄准
        BombThrow = 30,	// 手雷投掷
        UndefineCannotMove = 31,   // 不Care的不可移动状态（一般用于表演动画）
        DodgeSprint = 32,   // 冲刺
        BombReload = 33,    // 手雷装弹
        RPGAim = 34,    // 火箭筒瞄准
        RPGShoot = 35,  // 火箭筒射击
        RPGReload = 36, // 火箭筒装弹
        RPGReloadStart = 37, // 火箭筒装弹开始 (显示弹夹)
        HandGunReloadStart = 38,    // 手枪装弹开始 (显示弹夹)
        AutoRifleReloadStart = 39,  // 自动步枪装弹开始 （显示弹夹）
        
        // 特殊状态
        BulletElement = 10000,    // 子弹触发元素
    }
    
    // 当前人物作战状态
    /*
     * Tips:
     * 1. 新增作战状态后，请修改AIData的canBeThreaten方法告知该作战状态是否可以被恐吓；
     * 2. 新增作战状态后，请修改AnimationAgent的CanDoNextAnimation方法告知该作战状态什么时候可以接下个动作；
     */
    public enum BattleState
    {
        None = 0,   // 空闲
        Boxing = 1,     // 近战
        HandGun = 2,    // 手枪
        AutoRifle = 3,  // 自动步枪
        Bomb = 4, // 手雷
        RPG = 5, // 火箭筒
    }

    // 人物瞄准状态
    public enum AimingState
    {
        None = 0,   // 不瞄准
        NormalAim = 1, // 普通准星
        ReloadAim = 2,    // 装弹
        Grenade = 3,    // 手雷
    }
    
    [Serializable]
    public class AIData
    {
        public int uniqueId;

        public AIState state;
        
        // 基础动画状态 (Base Layer)
        public AnimationState baseAnimationState;

        // 所有动画层的动画状态 (All Layer)
        public AnimationState[] allAnimationStates = new AnimationState[6];
        
        // 当前的动画状态 (根据上身状态和当前状态得出)
        public AnimationState animationState
        {
            get
            {
                AnimationState result = AnimationState.Undefine;
                for (int i = 1; i < allAnimationStates.Length; ++i)
                {
                    switch (allAnimationStates[i])
                    {
                        case AnimationState.Undefine:
                        case AnimationState.Idle:
                        {
                            continue;
                        }

                        default:
                        {
                            result = allAnimationStates[i];
                            break;
                        }
                    }
                }
                switch (result)
                {
                    case AnimationState.Undefine:
                    case AnimationState.Idle:
                        {
                            // 否则使用当前动画状态
                            return baseAnimationState;
                        }
                        break;

                    default:
                        {
                            // 上身动画状态不在待机状态，就使用上身状态
                            return result;
                        }
                        break;
                }
            }
        }
        
        // 当前动画状态是否不可移动 (接收输入)
        public bool cannotAnimationStateMove
        {
            get
            {
                switch (animationState)
                {
                    case AnimationState.UndefineCannotMove:
                    case AnimationState.BehaviourPuppet:
                    {
                        return true;
                    }
                }
                
                // case AnimationState.Idle:
                // case AnimationState.Locomotion:
                // case AnimationState.HandGunShoot:
                // case AnimationState.HandGunReload:
                // case AnimationState.Sprinting:
                return false;
            }
        }
        
        // 当前动画状态是否含有根位移
        public bool animationStateHasRootMotion
        {
            get
            {
                switch (animationState)
                {
                    case AnimationState.Undefine:
                    case AnimationState.BoxingAttackDown:
                    case AnimationState.BoxingAttackKick:
                    case AnimationState.BoxingCombo1:
                    case AnimationState.BoxingCombo2:
                    case AnimationState.BoxingCombo3:
                    // case AnimationState.OnHit:
                    case AnimationState.OnHitDown:
                    case AnimationState.OnHitGetUp:
                    case AnimationState.BehaviourPuppet:
                    case AnimationState.HandGunBoxing:
                    case AnimationState.BoxingMove:
                    case AnimationState.BoxingRunAttack:
                    case AnimationState.BoxingAOE:
                    {
                        return true;
                    }
                }
                
                return false;
            }
        }

        // 当前动画状态是否使用IK
        public bool animationStateUseIK
        {
            get
            {
                switch (animationState)
                {
                    case AnimationState.HandGunShoot:
                    case AnimationState.HandGunAim:
                    case AnimationState.HandGunReload:
                    case AnimationState.AutoRifleShoot:
                    case AnimationState.AutoRifleAim:
                    case AnimationState.AutoRifleReload:
                    case AnimationState.RPGShoot:
                    case AnimationState.RPGAim:
                    case AnimationState.RPGReload:
                    {
                        return true;
                    }
                }

                return false;
            }
        }

        // 所属阵营
        public SideType side
        {
            get => _side;
            set
            {
                _side = value;
                // 设置受击触发器的Tag
                AIEntity aiEntity = LibertyAIUtils.GetNpc(uniqueId);
                if (aiEntity)
                {
                    string strSide = _side.ToString();
                    if (aiEntity.onHitCollider)
                    {
                        aiEntity.onHitCollider.gameObject.tag = strSide;
                    }
                    if (aiEntity.headCollider)
                    {
                        aiEntity.headCollider.gameObject.tag = strSide;
                    }
                }
            }
        }
        [SerializeField]
        private SideType _side;
        
        // 是否是Boss
        public bool isBoss = false;
        
        // 当前的作战状态 (实时)
        public BattleState battleState;
        
        // 当前瞄准状态 (实时)
        public AimingState aimingState;

        // // 选择的武器ID
        // public int selectedWeaponId = 0;
        
        // 是否在冲刺状态
        public bool isSprint = false;

        /// <summary>
        /// 当前状态是否可以被恐吓
        /// </summary>
        public bool canBeThreaten
        {
            get
            {
                if (!isAlive)
                {
                    return false;
                }
                
                switch (npcStatus)
                {
                    case NpcStatus.OnHit:
                    case NpcStatus.Escape:
                    case NpcStatus.VehicleBarge:
                    case NpcStatus.Battle:
                        {
                            return false;    
                        }
                        break;
                }

                switch (battleState)
                {
                    case BattleState.Boxing:
                    case BattleState.HandGun:
                    case BattleState.AutoRifle:
                    case BattleState.RPG:
                        {
                            return false;
                        }
                        break;
                }
                
                return true;
            }
        }

        /// <summary>
        /// 当前状态是否可以被推开
        /// </summary>
        public bool canBeBarge
        {
            get
            {
                if (!isAlive)
                {
                    return false;
                }

                switch (side)
                {
                    case SideType.Protected:
                        {
                            return false;
                        }
                        break;
                }
                
                switch (npcStatus)
                {
                    case NpcStatus.OnHit:
                    case NpcStatus.Escape:
                    case NpcStatus.VehicleBarge:
                    case NpcStatus.Battle:
                        {
                            return false;    
                        }
                        break;
                }
                
                return true;
            }
        }

        public NpcStatus npcStatus;

        public NpcStyle npcStyle;
        
        public bool isStreetEvent;
        
        // AI出生默认状态
        public NpcStatus defaultNpcStatus;
        // {
        //     get
        //     {
        //         switch (npcStyle)
        //         {
        //             case NpcStyle.Static:
        //                 {
        //                     return NpcStatus.StaticAction;
        //                 }
        //                 break;
        //             case NpcStyle.PathWalker:
        //                 {
        //                     return NpcStatus.PathControl;
        //                 }
        //                 break;
        //             case NpcStyle.StreetEvent:
        //                 {
        //                     return NpcStatus.None;
        //                 }
        //                 break;
        //             default:
        //                 {
        //                     return NpcStatus.StaticAction;
        //                 }
        //                 break;
        //         }
        //     }
        // }
        
        // NPC的行为模型
        public NpcAIModel npcAIModel
        {
            get
            {
                AIEntity aiEntity = LibertyAIUtils.GetNpc(uniqueId);
                if (aiEntity)
                {
                    return (NpcAIModel)aiEntity.propertyDataConfig.ai_model;
                }
                return NpcAIModel.Escape;
            }
        }

        private Vector3 _position;
        public Vector3 position
        {
            get
            {
                return _position;
            }
            set
            {
                _position = value;
                // FixedPosition = value;
            }
        }

        private Vector3 _currutLerpPosition;
        /// <summary>
        /// 当前正在Lerp的位置，除了强行设置位置和lerp完成 都不要设置此值
        /// </summary>
        public Vector3 CurrentLerpPositin
        {
            get
            {
                return _currutLerpPosition;
            }
        }
        public Vector3 TargetLerpPosition;
    
        public Vector3 destination;
        public Vector3 TargetLerpRotation;
        public Vector3 CurrentLerpRotation;

        // [SerializeField]
        // private Quaternion _rotation;
        public Quaternion rotation
        {
            get => Quaternion.Euler(CurrentLerpRotation);
        }

        public void SetCurrentPosition(Vector3 position)
        {
            _currutLerpPosition = position;
        }
        // [SerializeField]
        // private Vector3 _eulerAngles;
        // public Vector3 eulerAngles
        // {
        //     get => _eulerAngles;
        //     set
        //     {
        //         _eulerAngles = value;
        //         // FixedRotation = value;
        //         _rotation = Quaternion.Euler(value);
        //         _forward = (_rotation * Vector3.forward).normalized;
        //     }
        // }
        
        // [SerializeField]
        // private Vector3 _forward;
        public Vector3 forward
        {
            get =>  Quaternion.Euler(CurrentLerpRotation) * Vector3.forward.normalized;
        }

        // 移动相关参数
        // 移动加速度
        public static float moveAccelerrate = 10f;
        // 瞄准方向
        public Vector3 aimDirection = Vector3.zero;
        // 移动速度
        public float moveSpeed = 0;
        // 移动方向
        public Vector3 moveDirection = Vector3.zero;
        // 摇杆偏移值 正常情况下是[0, 1]
        public float maxSpeed;
        // 当前状态移动速度系数
        public float moveSpeedFactor
        {
            get
            {
                AIEntity aiEntity = LibertyAIUtils.GetNpc(uniqueId);
                if (aiEntity.WeaponSystem.HandleWeapon != null)
                {
                    PbWeaponDataConfig weaponDataConfig = aiEntity.WeaponSystem.HandleWeapon.Config;
                    if (weaponDataConfig != null)
                    {
                        // 瞄准状态速度比例
                        if (aimingState != AimingState.None)
                        {
                            return weaponDataConfig.movespeed_aim;
                        }

                        if (isSprint)
                        {
                            return weaponDataConfig.movespeed_sprint;
                        }
                    
                        // 待机状态速度比例
                        return weaponDataConfig.movespeed_idle;
                    }
                }
                return 1;
            }
        }

        
        // 和玩家的水平面距离 (每秒刷新N次)
        public float distanceToPlayer = float.MaxValue;
        // 和玩家的水平面方向 (每秒刷新N次)
        public Vector3 directionToPlayer = Vector3.zero;

        public string animState;
        
        public PathDirection pathDirection;
        public int pathId;
        public int pathPointIndex;
        

        public SpeedStrategyType speedStrategy = SpeedStrategyType.Const;
        
        public float pathOffsetFactor;

        //public bool isStatic;
        
        public Vector3 eventPosition;

        // 当前血量
        public int hp;
        // 血量下限
        public int minHp = 0;
        
        public bool invincible;

        public bool animInvincible;  // 动画无敌状态
        
        public bool ApplyDamage(int damageHp)
        {
            if (!invincible && !animInvincible)
            {
                hp -= damageHp;
                hp = Mathf.Max(hp, minHp);
                return true;
            }
            return false;
        }
        
        // 当前韧性值
        public int reduceToughness;
        // 最大人性值
        public int maxToughness;
        // 是否存活
        public bool isAlive => hp > 0;

        public bool isBombFly;
        // 远程武器位置
        public Vector3 rangedWeaponFirePosition = Vector3.zero;
        
        // 瞄准位置
        public Vector3 aimPosition
        {
            get {
                if (uniqueId == LibertyAIUtils.PLAYER_AI_ID)
                {
                    // 玩家瞄准位置从准星处获取
                    Transform lockPoint = LibertyAIUtils.PlayerController.playerLockTargetHelper.GetCurrentLockTargetEffect();
                    if (lockPoint)
                    {
                        return lockPoint.position;
                    }
                    else
                    {
                        return Vector3.zero;
                    }
                }
                else
                {
                    // AI瞄准位置由目标(GameObject)获取
                    AIEntity aiEntity = LibertyAIUtils.GetNpc(uniqueId);
                    AIEntity lockTarget = aiEntity.battleAgent.currentLockTarget;
                    if (lockTarget)
                    {
                        Transform upperChestBone = lockTarget.viewer.animator.GetBoneTransform(HumanBodyBones.UpperChest);
                        if (upperChestBone)
                        {
                            return upperChestBone.position;
                        }
                        else
                        {
                            if (lockTarget.characterController)
                            {
                                return lockTarget.viewer.animator.transform.position + new Vector3(0, lockTarget.characterController.height * 0.7f, 0);
                            }
                            else
                            {
                                var targetTransform = lockTarget.viewer.animator.transform;
                                var collider = targetTransform.GetComponent<Collider>();
                                if (collider)
                                {
                                    return targetTransform.position + new Vector3(0, collider.bounds.size.y * 0.7f, 0);
                                }
                                return targetTransform.position;
                            }
                        }
                    }
                    else
                    {
                        return Vector3.zero;
                    }
                }
            }
        }
        
        // 当前选中的包围点索引
        public int surroundIndex = -1;

    }
}